package com.ceair.authorization.handler;

import com.ceair.config.MyUrlConfig;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.OAuth2DeviceCode;
import org.springframework.security.oauth2.core.OAuth2UserCode;
import org.springframework.security.oauth2.core.endpoint.OAuth2DeviceAuthorizationResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.core.http.converter.OAuth2DeviceAuthorizationResponseHttpMessageConverter;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2DeviceAuthorizationRequestAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContextHolder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.IOException;

/**
 * @author wangbaohai
 * @ClassName DeviceAuthorizationResponseHandler
 * @description: 设备码认证成功响应
 * @date 2024年11月21日
 * @version: 1.0.0
 */
public class DeviceAuthorizationResponseHandler implements AuthenticationSuccessHandler {

    /**
     * 设备授权HTTP响应转换器
     * 用于将HTTP响应消息转换为OAuth2设备授权响应对象
     */
    private final HttpMessageConverter<OAuth2DeviceAuthorizationResponse> deviceAuthorizationHttpResponseConverter =
            new OAuth2DeviceAuthorizationResponseHttpMessageConverter();

    /**
     * 当设备认证成功时调用的方法
     *
     * @param request HTTP请求对象，包含请求相关信息
     * @param response HTTP响应对象，用于向客户端发送响应
     * @param authentication 认证信息对象，包含用户认证相关数据
     * @throws IOException 如果在处理过程中发生I/O错误
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException {
        // 将认证信息转换为设备授权请求认证令牌
        OAuth2DeviceAuthorizationRequestAuthenticationToken deviceAuthorizationRequestAuthentication =
                (OAuth2DeviceAuthorizationRequestAuthenticationToken) authentication;

        // 从认证令牌中获取设备码和用户码
        OAuth2DeviceCode deviceCode = deviceAuthorizationRequestAuthentication.getDeviceCode();
        OAuth2UserCode userCode = deviceAuthorizationRequestAuthentication.getUserCode();

        // 获取发行者URI
        String issuerUri = AuthorizationServerContextHolder.getContext().getIssuer();

        // 根据设备激活URI的绝对性构建基础URI
        UriComponentsBuilder uriComponentsBuilder;
        if (UrlUtils.isAbsoluteUrl(MyUrlConfig.DEVICE_ACTIVATE_URI)) {
            uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(MyUrlConfig.DEVICE_ACTIVATE_URI);
        } else {
            uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(issuerUri)
                    .path(MyUrlConfig.DEVICE_ACTIVATE_URI);
        }

        // 构建验证URI
        String verificationUri = uriComponentsBuilder.build().toUriString();

        // 构建完整的验证URI，包含用户码作为查询参数
        String verificationUriComplete = uriComponentsBuilder
                .queryParam(OAuth2ParameterNames.USER_CODE, userCode.getTokenValue())
                .build().toUriString();

        // 创建设备授权响应对象，包含设备码、用户码和验证URI等信息
        OAuth2DeviceAuthorizationResponse deviceAuthorizationResponse =
                OAuth2DeviceAuthorizationResponse.with(deviceCode, userCode)
                        .verificationUri(verificationUri)
                        .verificationUriComplete(verificationUriComplete)
                        .build();

        // 创建HTTP响应对象
        ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);

        // 使用设备授权HTTP响应转换器写入响应
        this.deviceAuthorizationHttpResponseConverter.write(deviceAuthorizationResponse, null, httpResponse);
    }

}
